package view.vo
{
    import flash.display.*;
    import flash.events.*;
    import flash.text.*;
    import mx.collections.ArrayCollection;
    import mx.controls.Alert;
    import mx.controls.Text;
    import mx.core.UIComponent;

    public class ClusterGraphics extends UIComponent
    {
        public var dataProvider:ArrayCollection;

        private var transX:int;
        private var transY:int;
        private var dX:int;
        private var dY:int;

        private static var WIDTH:int = 270;
        private static var HEIGHT:int = 230;

        public function ClusterGraphics()
        {
        }

        private function clearBox():void
        {
            for(var i:int=this.numChildren; i>0; i--)
            {
                var box:Sprite = Sprite(this.getChildAt(i-1));
                box.removeEventListener(MouseEvent.MOUSE_OVER, mouseOver);
                box.removeEventListener(MouseEvent.MOUSE_OUT, mouseOut);
                this.removeChildAt(i-1);
            }
        }

        private function preDraw():void
        {
            var itemCount:int = 0;
            var itemLength:int = 0;
            var maxY:int = 0;
            this.clearBox();
            for(var i:int=0; i<this.dataProvider.length; i++)
            {
                var list:Array = this.dataProvider[i];
                for(var j:int=0; j<list.length; j++)
                {
                    itemCount++;
                    var item:Array = list[j];
                    for(var k:int=0; k<item.length; k++)
                    {
                        if(maxY < item[k]) maxY = item[k];
                    }
                }
            }

            if(item.length > 0) itemLength = item.length;
            dX = ClusterGraphics.WIDTH / (itemCount+itemLength);
            dY = (2*ClusterGraphics.HEIGHT-dX*(itemCount+itemLength)) / maxY;
            transX = 2 * (ClusterGraphics.WIDTH - itemLength * dX);
            transY = maxY * dY + 2 * dX;
            /*
            Alert.show(" TransX = " + transX +
                       "\n TransY = " + transY +
                       "\n dX = " + dX +
                       "\n dY = " + dY +
                       "\n itemCount = " + itemCount +
                       "\n itemLength = " + itemLength +
                       "\n maxY = " + maxY);*/
        }

        private function drawBox(x:int, y:int, h:int, id:int, cls:int, c:uint):void
        {
            var X:int = transX + 2*dX*(y-x);
            var Y:int = transY + dX*(x+y);
            var box:Sprite = new Sprite();

            box.graphics.lineStyle(1, 0xcccccc, 1, true, "normal", "ROUND", "ROUND");
            
            // Top
            box.graphics.beginFill(c);
            box.graphics.moveTo(X, Y-h*dY);
            box.graphics.lineTo(X+2*dX, Y-dX-h*dY);
            box.graphics.lineTo(X, Y-2*dX-h*dY);
            box.graphics.lineTo(X-2*dX, Y-dX-h*dY);
            box.graphics.lineTo(X, Y-h*dY);
            box.graphics.endFill();

            // Front Left
            box.graphics.beginFill(darkColor(c));
            box.graphics.moveTo(X, Y);
            box.graphics.lineTo(X, Y-h*dY);
            box.graphics.lineTo(X-2*dX, Y-dX-h*dY);
            box.graphics.lineTo(X-2*dX, Y-dX);
            box.graphics.lineTo(X, Y);
            box.graphics.endFill();

            // Front Right
            box.graphics.beginFill(darkColor(c));
            box.graphics.moveTo(X, Y);
            box.graphics.lineTo(X+2*dX, Y-dX);
            box.graphics.lineTo(X+2*dX, Y-dX-h*dY);
            box.graphics.lineTo(X, Y-h*dY);
            box.graphics.lineTo(X, Y);
            box.graphics.endFill();

            this.addChild(box);
            box.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
            box.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
            box.name = "\tID:\t\t" + id.toString() +
                       "\n\tClass:\t" + cls.toString() +
                       "\n\tData:\t" + h.toString();
        }

        public function mouseOver(e:MouseEvent):void
        {
            var box:Sprite = Sprite(e.target);
            var t:TextField = new TextField();
            t.alpha = 0.1;
            t.background = true;
            t.backgroundColor = 0x330066;
            t.border = true;
            t.borderColor = 0xffff00;
            t.htmlText = "<span><b>" + box.name + "</b></span>";
            t.textColor = 0xff0000;
            t.width = 100;
            t.height = 55;
            t.x = 10;
            t.y = 10;
            box.blendMode = BlendMode.HARDLIGHT;
            addChild(t);
        }

        public function mouseOut(e:MouseEvent):void
        {
            var box:Sprite = Sprite(e.target);
            removeChildAt(numChildren-1);
            box.blendMode = BlendMode.NORMAL;
        }

        private function darkColor(c:uint):uint
        {
            var color:uint = 0;
            var r:uint = c / 0x010000;
            var g:uint = (c % 0x010000) / 0x000100;
            var b:uint = c % 0x000100;
            color = ((r/2)<<16) + ((g/2)<<8) + (b/2);
            return color;
        }

        private function randBitColor():uint
        {
            var c:uint = Math.random() * 255;
            return c;
        }

        private function randColor():uint
        {
            var c:uint = 0;
            var r:uint = randBitColor();
            var g:uint = randBitColor();
            var b:uint = Math.sqrt(255*255 - r*r - g*g);
            c = (r<<16) + (g<<8) + b;
            return c;
        }

        public function draw():void
        {
            var itemCount:int = 0;
            var classCount:int = 0;
            this.preDraw();
            for(var i:int=0; i<this.dataProvider.length; i++)
            {
                var list:Array = this.dataProvider[i];
                var c:uint = randColor();
                classCount++;
                for(var j:int=0; j<list.length; j++)
                {
                    var item:Array = list[j];
                    for(var k:int=0; k<item.length; k++)
                    {
                        this.drawBox(itemCount, k, item[k], itemCount, classCount, c);
                    }
                    itemCount++;
                }
            }
        }
    }
}
